
import { EventTouch, instantiate, Label, Node, Prefab, UITransform, view } from "cc";
import { UICF, UIID } from "../../game/config/Config";
import { BaseUI } from "../base/BaseUI";
import { BaseEventName, OrderLayer, UIConf } from "../config/Appcfg";
import { EventMgr } from "./EventMgr";
import { LogMgr } from "./LogMgr";
import { ResourceMgr } from "./ResourceMgr";

class UIConfig {
    constructor(uid: UIID, fromId: UIID, parent: Node, callback: Function, param1?: any, param2?: any, param3?: any, param4?: any, param5?: any) {
        this.uid = uid;
        this.callback = callback
        this.parent = parent
        this.fromId = fromId;
        this.param1 = param1;
        this.param2 = param2;
        this.param3 = param3;
        this.param4 = param4;
        this.param5 = param5;
    }
    uid: UIID;
    fromId: UIID;
    callback: Function;
    parent: Node;
    param1?: any;
    param2?: any;
    param3?: any;
    param4?: any;
    param5?: any;
}
export class UIMgr {




    private static _instance: UIMgr = null;
    protected constructor() { }
    public static getInstance(): UIMgr {
        if (this._instance == null) {
            this._instance = new UIMgr();
        }
        return this._instance;
    }
    public static get instance() {
        return UIMgr.getInstance()
    }

    private uistatck: Map<UIID, BaseUI> = new Map<number, BaseUI>();
    private uichace: Map<UIID, BaseUI> = new Map<number, BaseUI>();
    private orderMap: Map<number, number> = new Map();
    private UINodeMap: Map<UIID, Node> = new Map();
    private popStatck: UIConfig[] = [];
    private logStatck: UIConfig[] = [];
    private watingOpen: UIConfig[] = [];
    private onlyShowOne: OrderLayer[] = []
    private activityOne: OrderLayer[] = []
    private layerNodeMap: Map<number, Node[]> = new Map();
    /**其他的ui配置 */
    private otherUIConf: { [key: string]: UIConf }[] = []
    private uiRoot: Node = null;
    /** UI配置 */
    private UIConf: { [key: number]: UIConf } = {};
    private isopening: boolean = false;
    private tipsNode: Node;
    /**预加载UI 返回节点  */
    public preLoadUI(uid: any, callback: Function) {
        let uiconfig = this.getUICnf(uid)
        if (!uiconfig) {
            LogMgr.getInstance().error("ui没有配置：", uid)
            return;
        }
        //从本地加载
        ResourceMgr.getInstance().loadRes(uiconfig.bundleName, uiconfig.prefab, Prefab, (res: Prefab) => {
            let node = instantiate(res)
            node.name = uiconfig.name;
            let baseUi = node.getComponent(BaseUI)
            this.uichace.set(uid, baseUi);
            if (callback) {
                callback(node);
            }
        })
    }
    /**添加哪个层 同时只能显示一个 默认已经有pop层 不能添加main层*/
    public addLayerShowOne(layer: OrderLayer) {
        this.onlyShowOne.push(layer)
    }
    /**添加哪个层级 只能显示一个 其他全部activity=false 默认已经有main层 不能添加pop层*/
    public addLayerActivityOne(layer: OrderLayer) {
        this.activityOne.push(layer)
    }
    /**添加其他的UI配置 */
    public addUICnf(cnf: { [key: string]: UIConf }) {
        this.otherUIConf.push(cnf)
    }
    public setConf(conf: { [key: number]: UIConf }) {
        this.UIConf = conf
    }
    /**初始化 需要ui根节点 */
    public Init(root: Node) {
        this.uiRoot = root;
        this.UIConf = UICF
        this.touchTime = -1;
        // this.addTipsNode();
    }
    private touchTime: number = -1;
    private touchNum: number;
    private addTipsNode() {
        if (this.tipsNode) {
            this.tipsNode.destroy();
        }
        this.tipsNode = new Node();
        this.tipsNode.addComponent(UITransform)
        this.tipsNode.getComponent(UITransform).height = view.getVisibleSize().height;
        this.tipsNode.getComponent(UITransform).width = view.getVisibleSize().width;
        let labelNode = new Node();
        let label = labelNode.addComponent(Label)
        // Label.string = "著作权人：实丰（深圳）网络科技有限公司"
        label.string = "\u8457\u4f5c\u6743\u4eba\uff1a\u5b9e\u4e30\uff08\u6df1\u5733\uff09\u7f51\u7edc\u79d1\u6280\u6709\u9650\u516c\u53f8"
        label.fontSize = 20
        labelNode.parent = this.tipsNode;
        let y = -(view.getVisibleSize().height / 2 - 20)
        labelNode.setPosition(0, y, 0)
        labelNode.active = false;
        this.tipsNode.parent = this.uiRoot;
        this.tipsNode.getComponent(UITransform).priority = 99999
        this.tipsNode.on(Node.EventType.TOUCH_START, (event: EventTouch) => {
            event.preventSwallow = (true);
            let nowTime = new Date().getTime()
            if (this.touchTime != -1 && nowTime - this.touchTime < 200) {
                this.touchNum++;
            } else {
                this.touchNum = 0;
            }
            if (this.touchNum >= 20) {
                labelNode.active = true;
            }
            this.touchTime = new Date().getTime();
        })
    }
    public addNode(uid: UIID, zIndex: number) {
        let uiconfig = this.getUICnf(uid)
        if (uiconfig == null) {
            LogMgr.getInstance().debug(uid + "不存在")
            return;
        }
        //从本地加载
        ResourceMgr.getInstance().loadRes(uiconfig.bundleName, uiconfig.prefab, Prefab, (res: Prefab) => {
            let node = instantiate(res)
            node.name = uiconfig.name;
            this.uiRoot.addChild(node)
            node.getComponent(UITransform).priority = zIndex;
            this.UINodeMap.set(uid, node)
        })
    }
    /**显示节点 */
    public showNodeByUIID(uid: UIID) {
        let node = this.UINodeMap.get(uid)
        if (node == null) {
            LogMgr.getInstance().debug(uid + "不存在")
            return;
        }
        node.active = true;
    }
    /**隐藏节点 */
    public hideNodeByUIID(uid: UIID) {
        let node = this.UINodeMap.get(uid)
        if (node == null) {
            LogMgr.getInstance().debug(uid + "不存在")
            return;
        }
        node.active = false;
    }
    /**打开一个界面 指定父节点 */
    public openUIOfParent(uid: UIID, fromId: UIID, parent: Node, param1?: any, param2?: any, param3?: any, param4?: any, param5?: any) {
        this.open(uid, fromId, parent, param1, param2, param3, param4, param5)
    }
    /**打开界面 并且回调 */
    public openUIOfCallback(uid: UIID, fromId: UIID, callback: Function, param1?: any, param2?: any, param3?: any, param4?: any, param5?: any) {
        this.open(uid, fromId, this.uiRoot, callback, param1, param2, param3, param4, param5)
    }
    /**打开界面 指定父节点并且回调 */
    public openUIOfParentAndCallback(uid: UIID, fromId: UIID, parent: Node, callback: Function, param1?: any, param2?: any, param3?: any, param4?: any, param5?: any) {
        this.open(uid, fromId, parent, callback, param1, param2, param3, param4, param5)
    }
    /**
    * 打开一个界面
    * @param uid 界面的uid
    * @param params 透传参数
    */
    public openUI(uid: UIID, fromId: UIID, param1?: any, param2?: any, param3?: any, param4?: any, param5?: any) {
        this.open(uid, fromId, this.uiRoot, null, param1, param2, param3, param4, param5)
    }
    /**
     * 打开一个界面
     * @param uid 界面的uid
     * @param params 透传参数
     */
    private open(uid: UIID, fromId: UIID, parent: Node, callback: Function, param1?: any, param2?: any, param3?: any, param4?: any, param5?: any) {
        if (this.isopening) {
            let config = new UIConfig(uid, fromId, parent, callback, param1, param2, param3, param4, param5)
            this.watingOpen.push(config)

            return;
        }
        this.isopening = true;
        let uiconfig = this.getUICnf(uid)
        if (uiconfig == null) {
            LogMgr.getInstance().debug(uid + "不存在")
            this.isopening = false;
            return;
        }
        let config = new UIConfig(uid, fromId, parent, callback, param1, param2, param3, param4, param5)
        if (!this.popCanShow(uid, uiconfig, config)) {
            this.isopening = false;
            return;
        }
        if (this.uistatck.get(uid) && !uiconfig.showMult) {
            LogMgr.getInstance().debug(uid + "已经存在")
            let baseUI = this.uistatck.get(uid).node.getComponent(BaseUI)
            baseUI["refreshUI"](uid, fromId, callback, param1, param2, param3, param4, param5)
            this.isopening = false;
            return;
        }
        let baseUI = this.uichace.get(uid)
        if (baseUI) {
            this.uistatck.set(uid, baseUI)
            if (baseUI.init) {
                baseUI.init(param1, param2, param3, param4, param5)
            }
            this.uichace.delete(uid)
            //从缓存里面拿
            let node = parent.getChildByName(uiconfig.name)
            if (node == null) {
                node = baseUI.node
                node.active = false;
                node.name = uiconfig.name

                parent.addChild(node);
            }
            node.setPosition(0, 0)
            node.active = false;
            //设置层级
            baseUI.layer = uiconfig.zIndex
            let priority = uiconfig.zIndex
            if (this.orderMap.has(baseUI.layer)) {
                priority = this.orderMap.get(baseUI.layer) + 1
            }
            this.orderMap.set(baseUI.layer, priority)
            // node.getComponent(UITransform).priority = priority;
            baseUI["setUid"](uid);
            baseUI.fromId = fromId
            //刷新其他main层UI
            this.updateMainUI(uid, uiconfig)
            //添加到对应的层级
            let nodes = this.layerNodeMap.get(uiconfig.zIndex)
            if (nodes) {
                nodes.push(node)
            } else {
                let nods: Node[] = []
                nods.push(node)
                this.layerNodeMap.set(uiconfig.zIndex, nods)
            }
            //执行打开动画
            baseUI.openAni();
            if (callback) {
                callback(node)
            }
            EventMgr.getInstance().emit(BaseEventName.OpenUI, uid, node)
            this.isopening = false;
            this.openWaiting()
            node.active = true;
        } else {
            //从本地加载
            ResourceMgr.getInstance().loadRes(uiconfig.bundleName, uiconfig.prefab, Prefab, (res: Prefab) => {
                let node = instantiate(res)
                node.active = false;
                node.name = uiconfig.name;
                parent.addChild(node);
                let baseUi = node.getComponent(BaseUI)
                this.uistatck.set(uid, baseUi)
                if (baseUi.init) {
                    baseUi.init(param1, param2, param3, param4, param5);
                }
                baseUi.setUid(uid);
                baseUi.fromId = fromId
                //设置层级
                baseUi.layer = uiconfig.zIndex
                let priority = uiconfig.zIndex
                if (this.orderMap.has(baseUi.layer)) {
                    priority = this.orderMap.get(baseUi.layer) + 1
                }
                this.orderMap.set(baseUi.layer, priority)
                node.getComponent(UITransform).priority = priority;
                node.setPosition(0, 0)
                //刷新其他main层UI
                this.updateMainUI(uid, uiconfig)
                //添加到对应的层级
                let nodes = this.layerNodeMap.get(uiconfig.zIndex)
                if (nodes) {
                    nodes.push(node)
                } else {
                    let nods: Node[] = []
                    nods.push(node)
                    this.layerNodeMap.set(uiconfig.zIndex, nods)
                }
                //执行打开动画
                baseUi.openAni();
                if (callback) {
                    callback(node)
                }
                EventMgr.getInstance().emit(BaseEventName.OpenUI, uid, node)
                this.isopening = false;
                this.openWaiting()
                node.active = true;
            })
        }
    }
    /**
* getChildByName name:string    */
    public getChildByName(name: string): Node {
        let node = this.uiRoot.getChildByName(name)
        return node;
    }
    openWaiting() {
        if (this.watingOpen.length > 0) {
            let config = this.watingOpen.pop();
            this.openUIOfParentAndCallback(config.uid, config.fromId, config.parent, config.callback, config.param1, config.param2, config.param3, config.param4, config.param5)
        }
    }
    /**
     * 关闭一个界面
     * @param node 
     * @param params 
     */
    public closeUI(node: Node, param1?: any, param2?: any, param3?: any, param4?: any, param5?: any) {
        if (node == null || !node.isValid) {
            LogMgr.getInstance().debug("关闭失败")
            return;
        }
        let baseUI = node.getComponent(BaseUI)
        baseUI.closeAni(() => {
            let uid = baseUI.getUid();
            let uiconf = this.getUICnf(uid)
            baseUI.onClose();
            if (baseUI.cache) {
                node.removeFromParent()
                this.uichace.set(uid, baseUI)
            } else {
                node.destroy();
            }
            this.uistatck.delete(uid)
            if (uiconf == null) {
                return;
            }
            let nodes = this.layerNodeMap.get(uiconf.zIndex)
            if (nodes) {
                for (let i = 0; i < nodes.length; i++) {
                    let nods = nodes[i]
                    if (nods.name == node.name) {
                        nodes = nodes.splice(i, 1)
                        break
                    }
                }
            }
            //设置层级
            let priority = baseUI.layer
            if (this.orderMap.has(baseUI.layer)) {
                priority = this.orderMap.get(baseUI.layer) - 1
                if (priority < baseUI.layer) {
                    priority = baseUI.layer
                }
            }
            this.orderMap.set(baseUI.layer, priority)
            EventMgr.getInstance().emit(BaseEventName.CloseUI, uid, param1, param2, param3, param4)
            //当前关闭的是弹窗
            if (uiconf.zIndex == OrderLayer.pop) {
                if (this.popStatck.length > 0) {
                    let config = this.popStatck.pop()
                    this.openUIOfCallback(config.uid, config.fromId, config.callback, config.param1, config.param2, config.param3, config.param4, config.param5)
                }
            } else if (uiconf.zIndex == OrderLayer.main) {
                //关闭的是界面 
                let nodes = this.layerNodeMap.get(uiconf.zIndex)
                if (nodes && nodes.length > 0) {
                    // for (let i = 0; i < nodes.length; i++) {

                    // }
                    nodes[nodes.length - 1].active = true;
                }
            } else if (uiconf.zIndex == OrderLayer.Log) {
                //关闭的是界面 
                if (this.logStatck.length > 0) {
                    let config = this.logStatck.pop()
                    this.openUIOfCallback(config.uid, config.fromId, config.callback, config.param1, config.param2, config.param3, config.param4, config.param5)
                }
            }
            this.checkHomeShow();
        })
    }
    /**判断是否显示的是home */
    private checkHomeShow() {
        // let nodes = this.layerNodeMap.get(OrderLayer.main)
        // if (nodes.length == 1 && this.checkOtherEmpty()) {

        // }
    }
    private checkOtherEmpty() {
        let popNode = this.layerNodeMap.get(OrderLayer.pop)
        let pop2Node = this.layerNodeMap.get(OrderLayer.pop2)
        if (popNode && popNode.length > 0) {
            return false;
        }
        if (pop2Node && pop2Node.length > 0) {
            return false;
        }
        return true;
    }
    /**刷新ui */
    private updateMainUI(uid: UIID, uiconfig: UIConf) {
        // //每一个层的节点存起来
        // let nodes = this.layerNodeMap.get(uiconfig.zIndex)
        // //主界面需要全部隐藏
        // if (uiconfig.zIndex == OrderLayer.main) {
        //     if (nodes && nodes.length > 0) {
        //         let node: Node = nodes[nodes.length - 1]
        //         node.active = false;
        //         node.getComponent(BaseUI).onToggleHide(uid);
        //     }
        // }
    }
    /**弹窗是否需要排队 */
    private popCanShow(uid: UIID, uiconfig: UIConf, config: UIConfig): boolean {
        //每一个层的节点存起来
        let nodes = this.layerNodeMap.get(uiconfig.zIndex)
        if (uiconfig.zIndex == OrderLayer.pop) {
            //弹窗需要排队
            if (nodes && nodes.length > 0) {
                for (let i = 0; i < this.popStatck.length; i++) {
                    if (this.popStatck[i].uid == uid) {
                        return false;
                    }
                }
                this.popStatck.push(config);
                return false;
            }
        } else if (uiconfig.zIndex == OrderLayer.Log) {
            //弹窗需要排队
            if (nodes && nodes.length > 0) {
                this.logStatck.push(config);
                return false;
            }
        }
        return true;
    }
    /**
     * 根据uid关闭界面
     * @param uid 界面的uid
     * @param params 
     */
    public closeById(uid: number, param1?: any, param2?: any, param3?: any, param4?: any, param5?: any) {
        let baseUI = this.uistatck.get(uid)
        if (baseUI) {
            if (baseUI.node) {
                this.closeUI(baseUI.node, param1, param2, param3, param4, param5)
            } else {
                LogMgr.getInstance().debug("关闭失败2")
            }
        } else {
            LogMgr.getInstance().debug("关闭失败1")
        }
    }
    /**根据ui获取节点 */
    public getRootById(uid: UIID): Node {
        let ui = this.uistatck.get(uid)
        if (ui) {
            return ui.node;
        }
        let node = this.uiRoot.getChildByName(this.getUICnf(uid).name);
        if (node) {
            return node;
        }
        return null;
    }
    /**根据id获取ui */
    public getUIById(uid: UIID): BaseUI {
        let ui = this.uistatck.get(uid)
        if (ui) {
            return ui;
        }
        let node = this.uiRoot.getChildByName(this.getUICnf(uid).name);
        if (node) {
            return node.getComponent(BaseUI)
        }
        return null;
    }
    public getUIShowNum(uiid: UIID): number {
        let num: number = 0
        this.uistatck.forEach((v: BaseUI, uid: number) => {
            if (uid == uiid) {
                num++;
            }
        })
        return num;
    }
    /**根据id和父节点获取ui */
    public getUIByIdWithNode(uid: UIID, parent: Node): BaseUI {
        let ui = this.uistatck.get(uid)
        if (ui) {
            return ui;
        }
        if (parent == null) {
            return null;
        }
        let node = parent.getChildByName(this.getUICnf(uid).name);
        if (node) {
            return node.getComponent(BaseUI)
        }
        return null;
    }
    private getUICnf(uid: any): UIConf {
        let cfg = this.UIConf[uid]
        if (cfg) {
            return cfg;
        }
        for (let i = 0; i < this.otherUIConf.length; i++) {
            let conf = this.otherUIConf[i]
            let cfg = conf[uid]
            if (cfg) {
                return cfg;
            }
        }
        return null;
    }
    showLoadLayer(callback: Function) {
        this.openUI(UIID.UILoad, UIID.Default, 'show', callback)
    }
    hideLoadLayer(callback: Function) {
        this.openUI(UIID.UILoad, UIID.Default, 'hide', callback)
    }

    showTip(str: string) {
        UIMgr.getInstance().openUI(UIID.UITips, UIID.Default, str)
    }
}
